/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.saber.certificacao.ejbs.stateless;

import br.com.saber.certificacao.ejbs.stateless.interfaces.CertificacaoBeanLocal;
import br.com.saber.certificacao.ejbs.stateless.interfaces.VersaoBeanLocal;
import br.com.saber.certificacao.modelos.Certificacao;
import br.com.saber.certificacao.modelos.Questao;
import br.com.saber.certificacao.modelos.Usuario;
import br.com.saber.certificacao.modelos.Versao;
import br.com.saber.certificacao.modelos.validadores.CertificacaoValidador;
import br.com.saber.certificacao.modelos.validadores.interfaces.ValidadorInterface;
import java.util.Set;
import java.util.TreeSet;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 *
 * @author gbvbahia
 */
@Stateless
public class CertificacaoBean implements CertificacaoBeanLocal {

    @EJB
    private VersaoBeanLocal versaoBean;

    @PersistenceContext(name = "jdbc/saber")
    private EntityManager manager;

    @Override
    public void salvarCertificacao(Certificacao certificacao) {
        ValidadorInterface<Certificacao,CertificacaoBeanLocal> cv = new CertificacaoValidador();
        cv.validar(certificacao, this, null);
        if (certificacao.getId() == null) {
            manager.persist(certificacao);
        } else {
            manager.merge(certificacao);
        }
        manager.flush();
    }

    @Override
    public Certificacao buscarCertificacaoPorNome(String nomeCertificacao) {
        Query q = manager.createNamedQuery("CertificacaoBean.busrcarCertificacaoPorNome");
        q.setParameter("nome", nomeCertificacao);
        try {
            return (Certificacao) q.getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }

    @Override
    public Set<Certificacao> buscarTodasCertificacoes() {
        Query q = manager.createNamedQuery("CertificacaoBean.buscarTodasCertificacoes");
        return new TreeSet<Certificacao>(q.getResultList());
    }

    @Override
    public Certificacao buscarCertificascaoPorId(Long id) {
        return manager.find(Certificacao.class, id);
    }

    /**
     * Embora o método enfatiza professor, qualquer usuário pode ser
     * passado como parâmetro, Aluno, Professor, Coordenador.
     * Todas as certificações ligadas ao mesmo, atravéz de Versões
     * serão retornadas.
     * @param professor
     * @return Havendo uma ligação ProfessorVersao a certificação será retornada.
     */
    @Override
    public Set<Certificacao> buscarCertificacoesPorProfessor(Usuario professor) {
        Set<Certificacao> toReturn = new TreeSet();
        Set<Versao> versoes = versaoBean.buscarVersoesPorProfessor(professor);
        for (Versao v : versoes) {
            toReturn.add(v.getCertificacao());
        }
        return toReturn;
    }
    
    /**
     * Usuario possui relacionamento LEAZY com Certificações.
     * CertificacoesProfessorAcesso, este método carrega
     * essas certificações e retorna para o solicitante.
     * @param professor
     * @return 
     */
    public Set<Certificacao> loadLazyCertificacoesDoProfessor(Usuario professor){
        Usuario toLoad = this.manager.find(Usuario.class, professor.getId());
        return toLoad.getCertificacoesProfessorAcesso();
    }

    /**
     * Retorna todas as certificações que o coordenador é responsável.
     * Qualquer usuário pode ser passado, se ele não for coordenador ou se for mas
     * não tiver uma certificação como responsável será retornado cuma coleção set vazia.
     * @param coordenador
     * @return
     */
    @Override
    public Set<Certificacao> buscarCertificacoesPorCoordenador(Usuario coordenador) {
        Set<Certificacao> toReturn = new TreeSet();
        Query q = manager.createNamedQuery("CertificacaoBean.buscarCertificacaoPorCoordenador");
        q.setParameter("coordenador", coordenador);
        toReturn.addAll(q.getResultList());
        return toReturn;
    }

    /**
     * Esse método deve sempre retornar uma certificação, caso isso não ocorra
     * é porque existe inconsistência no banco de dados
     * @param questao
     * @return A certificação da questão
     */
    @Override
    public Certificacao buscarCertificacaoPorQuestao(Questao questao) {
        Query q = manager.createNamedQuery("CertificacaoBean.buscarCertificacaoPorQuestao");
        q.setParameter("questao", questao);
        return (Certificacao) q.getSingleResult();
    }

    /**
     * Retorna as certificações que possuem a no mínimo a quantidade de questões
     * passada como parêmetro.
     * @param quantidade minima de questões
     * @return Lista com as certificações que possuem a quantidade mínima de questões
     */
    @Override
    public Set<Certificacao> buscarCertificacaoComQuantidadeQuestoes(int quantidade) {
        Set<Versao> versoes = versaoBean.buscarVersoesComMinimoQuestoes(quantidade);
        Set<Certificacao> toReturn = new TreeSet<Certificacao>();
        for (Versao versao : versoes) {
            if (!toReturn.contains(versao.getCertificacao())) {
                toReturn.add(versao.getCertificacao());
            }
        }
        return toReturn;
    }
}
